from datetime import datetime, timedelta
from typing import Dict, List, Optional
from app.utils.elasticsearch import ESClient
from app.config.logging_config import get_logger
from app.services.user_service import UserService, UserInDB
from app.services.role_service import RoleService

logger = get_logger(__name__)

class StatisticsService:
    def __init__(self):
        self.es_client = ESClient.get_client()
        self.user_service = UserService()
        self.role_service = RoleService()
    
    async def get_user_statistics_overview(self, current_user: UserInDB, allowed_customs_codes: Optional[List[str]] = None) -> Dict:
        """获取用户统计概览"""
        try:
            # 获取用户权限下的海关编码
            user_codes = await self._get_user_accessible_codes(current_user, allowed_customs_codes)
            if not user_codes:
                return {
                    "total_updates": 0,
                    "involved_countries": 0,
                    "involved_companies": 0,
                    "accessible_codes": 0
                }

            # 计算昨天到今天的时间范围
            yesterday = datetime.now() - timedelta(days=1)
            today = datetime.now()
            
            # 为了确保包含今天的所有数据，将结束时间设为明天的开始
            tomorrow = today + timedelta(days=1)

            # 构建ES查询 - 查询从昨天开始到今天结束的数据
            query = {
                "query": {
                    "bool": {
                        "must": [
                            {"range": {"updated_at": {
                                "gte": yesterday.strftime("%Y-%m-%d"),
                                "lt": tomorrow.strftime("%Y-%m-%d")
                            }}}
                        ]
                    }
                },
                "size": 0,
                "aggs": {
                    "total_updates": {"value_count": {"field": "_id"}},
                    "involved_countries": {
                        "cardinality": {
                            "script": {
                                "source": "if (doc['进口商所在国家'].size() > 0 && doc['出口商所在国家'].size() > 0) { return doc['进口商所在国家'].value + '|' + doc['出口商所在国家'].value } else if (doc['进口商所在国家'].size() > 0) { return doc['进口商所在国家'].value } else if (doc['出口商所在国家'].size() > 0) { return doc['出口商所在国家'].value } else { return 'unknown' }"
                            }
                        }
                    },
                    "involved_companies": {
                        "cardinality": {
                            "script": {
                                "source": "if (doc['进口商'].size() > 0 && doc['出口商'].size() > 0) { return doc['进口商'].value + '|' + doc['出口商'].value } else if (doc['进口商'].size() > 0) { return doc['进口商'].value } else if (doc['出口商'].size() > 0) { return doc['出口商'].value } else { return 'unknown' }"
                            }
                        }
                    },
                    "date_range": {
                        "stats": {
                            "field": "日期"
                        }
                    }
                }
            }

            # 如果有海关编码限制，添加过滤条件
            if user_codes and user_codes != ["*"]:
                prefix_queries = []
                for code in user_codes:
                    prefix_queries.append({"prefix": {"海关编码": str(code)}})
                
                query["query"]["bool"]["must"].append({
                    "bool": {
                        "should": prefix_queries,
                        "minimum_should_match": 1
                    }
                })

            # 添加调试日志
            logger.info(f"统计概览查询: 用户={current_user.username}, 时间范围={yesterday.strftime('%Y-%m-%d')} 到 {tomorrow.strftime('%Y-%m-%d')}(不含)")
            logger.info(f"用户可访问编码: {user_codes}")
            logger.info(f"ES查询语句: {query}")
            
            response = self.es_client.search(index="customs_data", body=query)
            aggs = response.get("aggregations", {})
            
            # 添加结果日志
            total_hits = response.get("hits", {}).get("total", {}).get("value", 0)
            logger.info(f"查询命中记录数: {total_hits}")
            logger.info(f"聚合结果: {aggs}")

            # 处理日期范围统计
            date_range_stats = aggs.get("date_range", {})
            date_range = {
                "earliest_date": date_range_stats.get("min_as_string"),
                "latest_date": date_range_stats.get("max_as_string")
            }

            return {
                "total_updates": aggs.get("total_updates", {}).get("value", 0),
                "involved_countries": aggs.get("involved_countries", {}).get("value", 0),
                "involved_companies": aggs.get("involved_companies", {}).get("value", 0),
                "accessible_codes": len(user_codes) if user_codes and user_codes != ["*"] else -1,
                "date_range": date_range
            }

        except Exception as e:
            logger.error(f"获取用户统计概览失败: {str(e)}")
            raise

    async def get_detailed_statistics(self, current_user: UserInDB, start_date: str, end_date: str, allowed_customs_codes: Optional[List[str]] = None) -> Dict:
        """获取详细统计数据"""
        try:
            # 验证时间范围：只允许查询近一个月内的数据
            try:
                start_dt = datetime.strptime(start_date, "%Y-%m-%d")
                end_dt = datetime.strptime(end_date, "%Y-%m-%d")
                
                # 计算30天前的日期（只比较日期，不比较具体时间）
                thirty_days_ago = (datetime.now() - timedelta(days=30)).date()
                
                # 检查开始时间是否在30天内（只比较日期部分）
                if start_dt.date() < thirty_days_ago:
                    logger.warning(f"用户 {current_user.username} 尝试查询超过30天的数据: {start_date}")
                    return {"code_statistics": [], "error": "只能查询最近30天内的数据"}
                
                # 检查结束时间是否超过今天（只比较日期部分）
                if end_dt.date() > datetime.now().date():
                    logger.warning(f"用户 {current_user.username} 尝试查询未来时间的数据: {end_date}")
                    return {"code_statistics": [], "error": "不能查询未来时间的数据"}
                
                # 检查时间范围是否合理（开始时间不能晚于结束时间）
                if start_dt > end_dt:
                    logger.warning(f"用户 {current_user.username} 查询时间范围无效: {start_date} 到 {end_date}")
                    return {"code_statistics": [], "error": "开始时间不能晚于结束时间"}
                    
            except ValueError as e:
                logger.error(f"时间格式错误: {str(e)}")
                return {"code_statistics": [], "error": "时间格式错误，请使用YYYY-MM-DD格式"}

            user_codes = await self._get_user_accessible_codes(current_user, allowed_customs_codes)
            if not user_codes:
                return {"code_statistics": []}

            # 构建ES查询 - 为了确保包含end_date当天的所有数据，结束时间使用下一天的开始
            end_date_plus_one = (datetime.strptime(end_date, "%Y-%m-%d") + timedelta(days=1)).strftime("%Y-%m-%d")
            
            query = {
                "query": {
                    "bool": {
                        "must": [
                            {"range": {"updated_at": {"gte": start_date, "lt": end_date_plus_one}}}
                        ]
                    }
                },
                "size": 0,
                "aggs": {
                    "code_statistics": {
                        "terms": {"field": "海关编码", "size": 1000},
                        "aggs": {
                            "update_count": {"value_count": {"field": "_id"}},
                            "countries": {
                                "scripted_metric": {
                                    "init_script": "state.countries = new HashSet(); state.companies = new HashSet();",
                                    "map_script": """
                                        if (doc['进口商所在国家'].size() > 0) state.countries.add(doc['进口商所在国家'].value);
                                        if (doc['出口商所在国家'].size() > 0) state.countries.add(doc['出口商所在国家'].value);
                                        if (doc['进口商'].size() > 0) state.companies.add(doc['进口商'].value);
                                        if (doc['出口商'].size() > 0) state.companies.add(doc['出口商'].value);
                                    """,
                                    "combine_script": "return state;",
                                    "reduce_script": """
                                        def countries = new HashSet(); def companies = new HashSet();
                                        for (state in states) {
                                            countries.addAll(state.countries);
                                            companies.addAll(state.companies);
                                        }
                                        return ['countries': countries, 'companies': companies];
                                    """
                                }
                            },
                            "date_range": {
                                "stats": {
                                    "field": "日期"
                                }
                            }
                        }
                    }
                }
            }

            # 如果有海关编码限制，添加过滤条件
            if user_codes and user_codes != ["*"]:
                prefix_queries = []
                for code in user_codes:
                    prefix_queries.append({"prefix": {"海关编码": str(code)}})
                
                query["query"]["bool"]["must"].append({
                    "bool": {
                        "should": prefix_queries,
                        "minimum_should_match": 1
                    }
                })

            # 添加调试日志
            logger.info(f"详细统计查询: 用户={current_user.username}, 时间范围={start_date} 到 {end_date_plus_one}(不含)")
            logger.info(f"用户可访问编码: {user_codes}")
            logger.info(f"ES查询语句: {query}")
            
            response = self.es_client.search(index="customs_data", body=query)
            aggs = response.get("aggregations", {})
            
            # 添加结果日志
            total_hits = response.get("hits", {}).get("total", {}).get("value", 0)
            logger.info(f"查询命中记录数: {total_hits}")

            code_stats = []
            for bucket in aggs.get("code_statistics", {}).get("buckets", []):
                code = bucket["key"]
                update_count = bucket["update_count"]["value"]

                # 解析国家和公司信息
                countries = set()
                companies = set()
                if "countries" in bucket:
                    countries = set(bucket["countries"]['value']["countries"])
                    companies = set(bucket["countries"]['value']["companies"])

                # 处理日期范围信息
                date_range_stats = bucket.get("date_range", {})
                date_range = {
                    "earliest_date": date_range_stats.get("min_as_string"),
                    "latest_date": date_range_stats.get("max_as_string")
                }

                code_stats.append({
                    "code": code,
                    "update_count": update_count,
                    "countries": list(countries),
                    "companies": list(companies),
                    "date_range": date_range
                })

            return {"code_statistics": code_stats}

        except Exception as e:
            logger.error(f"获取详细统计数据失败: {str(e)}")
            raise

    async def _get_user_accessible_codes(self, current_user: UserInDB, allowed_customs_codes: Optional[List[str]] = None) -> List[str]:
        """获取用户有权限访问的海关编码"""
        try:
            # 如果传入了 allowed_customs_codes，直接使用
            if allowed_customs_codes is not None:
                return allowed_customs_codes

            # 如果为 None，根据用户权限判断
            # 只有管理员用户时，allowed_customs_codes为None才是全部代码
            if current_user.is_admin:
                return ["*"]
            
            # 其他用户None的时候就是可查的customs_code为空
            return []

        except Exception as e:
            logger.error(f"获取用户可访问编码失败: {str(e)}")
            return []